package com.security.control.app.validate.impl;

import com.security.control.core.validate.ValidateCodeRepository;
import com.security.control.core.validate.exception.ValidateCodeException;
import com.security.control.core.validate.support.ValidateCode;
import com.security.control.core.validate.support.ValidateCodeType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;

import java.util.concurrent.TimeUnit;

/**
 * @author imoot@gamil.com
 * @date 2019/1/19 0019 9:35
 * 基于redis的验证码存取器，避免没有session导致无法存取验证码
 */
@Component
public class RedisValidateCodeRepository implements ValidateCodeRepository {

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * @param request
     * @param code
     * @param validateCodeType
     * 把验证码（自定义的key和失效的时间）保存到redis中
     */
    @Override
    public void save(ServletWebRequest request, ValidateCode code, ValidateCodeType validateCodeType) {
        redisTemplate.opsForValue().set(buildKey(request, validateCodeType), code, 30, TimeUnit.MINUTES);
    }

    /**
     * @param request
     * @param validateCodeType
     * @return ValidateCode
     * 用key取出保存的验证码
     */
    @Override
    public ValidateCode get(ServletWebRequest request, ValidateCodeType validateCodeType) {
        Object value = redisTemplate.opsForValue().get(buildKey(request, validateCodeType));
        if (null == value) {
            return null;
        }
        return (ValidateCode) value;
    }

    /**
     * @param request
     * @param validateCodeType
     * 用key移除验证码
     */
    @Override
    public void remove(ServletWebRequest request, ValidateCodeType validateCodeType) {
        redisTemplate.delete(buildKey(request, validateCodeType));
    }

    /**
     * @param request
     * @param validateCodeType
     * @return String
     * 使用验证码类型和设备id生成key
     */
    private String buildKey(ServletWebRequest request, ValidateCodeType validateCodeType) {
        String deviceId = request.getHeader("deviceId");
        if (StringUtils.isBlank(deviceId)) {
            throw new ValidateCodeException("请在请求头中携带deviceId参数");
        }
        return "code:" + validateCodeType.toString().toLowerCase() + ":" + deviceId;
    }
}
